<template>
    <div class="detail-item" @click="goPostDetail(post.id)">
        <n-thing>
            <template #avatar>
                <n-avatar round :size="30" :src="post.user.avatar" />
            </template>
            <template #header>
                <router-link
                    @click.stop
                    class="username-link"
                    :to="{
                        name: 'user',
                        query: { s: post.user.username },
                    }"
                >
                    {{ post.user.nickname }}
                </router-link>
                <span class="username-wrap"> @{{ post.user.username }} </span>
                <n-tag
                    v-if="post.is_top"
                    class="top-tag"
                    type="warning"
                    size="small"
                    round
                >
                    置顶
                </n-tag>
                <n-tag
                    v-if="post.visibility == VisibilityEnum.PRIVATE"
                    class="top-tag"
                    type="error"
                    size="small"
                    round
                >
                    私密
                </n-tag>
                <n-tag
                    v-if="post.visibility == VisibilityEnum.FRIEND"
                    class="top-tag"
                    type="info"
                    size="small"
                    round
                >
                    好友可见
                </n-tag>
            </template>
            <template #header-extra>
                <div class="options">
                    <n-dropdown
                        placement="bottom-end"
                        trigger="click"
                        size="small"
                        :options="adminOptions"
                        @select="handlePostAction"
                    >
                        <n-button quaternary circle>
                            <template #icon>
                                <n-icon>
                                    <more-horiz-filled />
                                </n-icon>
                            </template>
                        </n-button>
                    </n-dropdown>
                </div>

                <!-- 删除确认 -->
                <n-modal
                    v-model:show="showDelModal"
                    :mask-closable="false"
                    preset="dialog"
                    title="提示"
                    content="确定删除该泡泡动态吗？"
                    positive-text="确认"
                    negative-text="取消"
                    @positive-click="execDelAction"
                />
                <!-- 锁定确认 -->
                <n-modal
                    v-model:show="showLockModal"
                    :mask-closable="false"
                    preset="dialog"
                    title="提示"
                    :content="
                        '确定' +
                        (post.is_lock ? '解锁' : '锁定') +
                        '该泡泡动态吗？'
                    "
                    positive-text="确认"
                    negative-text="取消"
                    @positive-click="execLockAction"
                />
                <!-- 置顶确认 -->
                <n-modal
                    v-model:show="showStickModal"
                    :mask-closable="false"
                    preset="dialog"
                    title="提示"
                    :content="
                        '确定' +
                        (post.is_top ? '取消置顶' : '置顶') +
                        '该泡泡动态吗？'
                    "
                    positive-text="确认"
                    negative-text="取消"
                    @positive-click="execStickAction"
                />
                <!-- 亮点确认 -->
                <n-modal
                    v-model:show="showHighlightModal"
                    :mask-closable="false"
                    preset="dialog"
                    title="提示"
                    :content="
                        '确定将该泡泡动态' +
                        (post.is_essence ? '取消亮点' : '设为亮点') +
                        '吗？'
                    "
                    positive-text="确认"
                    negative-text="取消"
                    @positive-click="execHighlightAction"
                />
                <!-- 修改可见度确认 -->
                <n-modal
                    v-model:show="showVisibilityModal"
                    :mask-closable="false"
                    preset="dialog"
                    title="提示"
                    :content="
                        '确定将该泡泡动态可见度修改为' +
                        (tempVisibility == 0 ? '公开' : (tempVisibility == 1 ? '私密' : (tempVisibility == 2 ? '好友可见' : '关注可见'))) +
                        '吗？'
                    "
                    positive-text="确认"
                    negative-text="取消"
                    @positive-click="execVisibilityAction"
                />
                  <!-- 私信组件 -->
                <whisper :show="showWhisper" :user="whisperReceiver" @success="whisperSuccess" />
            </template>
            <div v-if="post.texts.length > 0">
                <span
                    v-for="content in post.texts"
                    :key="content.id"
                    class="post-text"
                    @click.stop="doClickText($event, post.id)"
                    v-html="parsePostTag(content.content).content"
                >
                </span>
            </div>

            <template #footer>
                <post-attachment :attachments="post.attachments" />
                <post-attachment
                    :attachments="post.charge_attachments"
                    :price="post.attachment_price"
                />
                <post-image :imgs="post.imgs" />
                <post-video :videos="post.videos" :full="true" />
                <post-link :links="post.links" />
                <div class="timestamp">
                    发布于 {{ formatPrettyTime(post.created_on) }}
                    <span v-if="post.ip_loc">
                        <n-divider vertical />
                        {{ post.ip_loc }}
                    </span>
                    <span v-if="!store.state.collapsedLeft && post.created_on != post.latest_replied_on">
                        <n-divider vertical /> 最后回复
                        {{ formatPrettyTime(post.latest_replied_on) }}
                    </span>
                </div>
            </template>
            <template #action>
                <div class="opts-wrap">
                    <n-space justify="space-between">
                        <div
                            class="opt-item hover"
                            @click.stop="handlePostStar"
                        >
                            <n-icon size="20" class="opt-item-icon">
                                <heart-outline v-if="!hasStarred" />
                                <heart v-if="hasStarred" color="red" />
                            </n-icon>
                            {{ post.upvote_count }}
                        </div>
                        <div class="opt-item">
                            <n-icon size="20" class="opt-item-icon">
                                <chatbox-outline />
                            </n-icon>
                            {{ post.comment_count }}
                        </div>
                        <div
                            class="opt-item hover"
                            @click.stop="handlePostCollection"
                        >
                            <n-icon size="20" class="opt-item-icon">
                                <bookmark-outline v-if="!hasCollected" />
                                <bookmark v-if="hasCollected" color="#ff7600" />
                            </n-icon>
                            {{ post.collection_count }}
                        </div>
                        <div
                            class="opt-item hover"
                            @click.stop="handlePostShare"
                        >
                            <n-icon size="20" class="opt-item-icon">
                                <share-social-outline />
                            </n-icon>
                            {{ post.share_count }}
                        </div>
                    </n-space>
                </div>
            </template>
        </n-thing>
    </div>
</template>

<script setup lang="ts">
import { h, ref, onMounted, computed } from 'vue';
import type { Component } from 'vue'
import { NIcon, useDialog } from 'naive-ui'
import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
import { formatPrettyTime } from '@/utils/formatTime';
import { parsePostTag } from '@/utils/content';
import {
    PaperPlaneOutline,
    Heart,
    HeartOutline,
    Bookmark,
    BookmarkOutline,
    ShareSocialOutline,
    ChatboxOutline,
    PushOutline,
    TrashOutline,
    LockClosedOutline,
    LockOpenOutline,
    EyeOutline,
    EyeOffOutline,
    BodyOutline,
    WalkOutline,
    PersonOutline,
    FlameOutline,
} from '@vicons/ionicons5';
import { MoreHorizFilled } from '@vicons/material';
import {
    getPostStar,
    postStar,
    getPostCollection,
    postCollection,
    deletePost,
    lockPost,
    stickPost,
    highlightPost,
    visibilityPost
} from '@/api/post';
import { followUser, unfollowUser } from '@/api/user';
import type { DropdownOption } from 'naive-ui';
import { VisibilityEnum } from '@/utils/IEnum';
import copy from "copy-to-clipboard";

const useFriendship = (import.meta.env.VITE_USE_FRIENDSHIP.toLowerCase() === 'true')

const store = useStore();
const router = useRouter();
const dialog = useDialog();
const hasStarred = ref(false);
const hasCollected = ref(false);
const props = withDefaults(
    defineProps<{
        post: Item.PostProps;
    }>(),
    {}
);
const showDelModal = ref(false);
const showLockModal = ref(false);
const showStickModal = ref(false);
const showHighlightModal = ref(false);
const showVisibilityModal = ref(false);
const loading = ref(false);
const tempVisibility = ref<VisibilityEnum>(VisibilityEnum.PUBLIC);
const showWhisper = ref(false);
const whisperReceiver = ref<Item.UserInfo>({
    id: 0,
    avatar: '',
    username: '',
    nickname: '',
    is_admin: false,
    is_friend: true,
    is_following: false,
    created_on: 0,
    follows: 0,
    followings: 0,
    status: 1,
});

const onSendWhisper =  (user: Item.UserInfo) => {
    whisperReceiver.value = user;
    showWhisper.value = true;
};

const whisperSuccess = () => {
    showWhisper.value = false;
};

const emit = defineEmits<{
    (e: 'reload', post_id: number): void;
}>();

const post = computed({
    get: () => {
        let post: Item.PostComponentProps = Object.assign(
            {
                texts: [],
                imgs: [],
                videos: [],
                links: [],
                attachments: [],
                charge_attachments: [],
            },
            props.post
        );
        post.contents.map((content) => {
            if (+content.type === 1 || +content.type === 2) {
                post.texts.push(content);
            }
            if (+content.type === 3) {
                post.imgs.push(content);
            }
            if (+content.type === 4) {
                post.videos.push(content);
            }
            if (+content.type === 6) {
                post.links.push(content);
            }
            if (+content.type === 7) {
                post.attachments.push(content);
            }
            if (+content.type === 8) {
                post.charge_attachments.push(content);
            }
        });
        return post;
    },
    set: (newVal) => {
        props.post.upvote_count = newVal.upvote_count;
        props.post.comment_count = newVal.comment_count;
        props.post.collection_count = newVal.collection_count;
        props.post.is_essence = newVal.is_essence;
    },
});

const renderIcon = (icon: Component) => {
  return () => {
    return h(NIcon, null, {
      default: () => h(icon)
    })
  }
};

const adminOptions = computed(() => {
    let options: DropdownOption[] = [];
    if (!store.state.userInfo.is_admin && store.state.userInfo.id != props.post.user.id) {
       options.push({
            label: '私信 @' + props.post.user.username,
            key: 'whisper',
            icon: renderIcon(PaperPlaneOutline)
        });
        if (props.post.user.is_following) {
            options.push({
                label: '取消关注 @' + props.post.user.username,
                key: 'unfollow',
                icon: renderIcon(WalkOutline)
            })
        } else {
            options.push({
                label: '关注 @' + props.post.user.username,
                key: 'follow',
                icon: renderIcon(BodyOutline)
            })
        }
        return options;
    }
    options.push({
        label: '删除',
        key: 'delete',
        icon: renderIcon(TrashOutline)
    })
    if (post.value.is_lock === 0) {
        options.push({
            label: '锁定',
            key: 'lock',
            icon: renderIcon(LockClosedOutline)
        });
    } else {
        options.push({
            label: '解锁',
            key: 'unlock',
            icon: renderIcon(LockOpenOutline)
        });
    }
    if (store.state.userInfo.is_admin) {
        if (post.value.is_top === 0) {
            options.push({
                label: '置顶',
                key: 'stick',
                icon: renderIcon(PushOutline)
            });
        } else {
            options.push({
                label: '取消置顶',
                key: 'unstick',
                icon: renderIcon(PushOutline)
            });
        }
    }
    if (post.value.is_essence === 0) {
        options.push({
            label: '设为亮点',
            key: 'highlight',
            icon: renderIcon(FlameOutline)
        });
    } else {
        options.push({
            label: '取消亮点',
            key: 'unhighlight',
            icon: renderIcon(FlameOutline)
        });
    }
    let visitMenu: DropdownOption
    if (post.value.visibility === VisibilityEnum.PUBLIC) {
        visitMenu = {
            label: '公开',
            key: 'vpublic',
            icon: renderIcon(EyeOutline),
            children: [
                { label: '私密', key: 'vprivate', icon: renderIcon(EyeOffOutline) },
                { label: '关注可见', key: 'vfollowing', icon: renderIcon(BodyOutline) }
            ]
        };
    } else if (post.value.visibility === VisibilityEnum.PRIVATE) {
        visitMenu = {
            label: '私密',
            key: 'vprivate',
            icon: renderIcon(EyeOffOutline),
            children: [
                { label: '公开', key: 'vpublic', icon: renderIcon(EyeOutline) },
                { label: '关注可见', key: 'vfollowing', icon: renderIcon(BodyOutline) }
            ]
        };
    } else if (useFriendship && post.value.visibility === VisibilityEnum.FRIEND) {
        visitMenu = {
            label: '好友可见',
            key: 'vfriend',
            icon: renderIcon(PersonOutline),
            children: [
                { label: '公开', key: 'vpublic', icon: renderIcon(EyeOutline) },
                { label: '私密', key: 'vprivate', icon: renderIcon(EyeOffOutline) },
                { label: '关注可见', key: 'vfollowing', icon: renderIcon(BodyOutline) }
            ]
        };
    } else {
       visitMenu = {
            label: '关注可见',
            key: 'vfollowing',
            icon: renderIcon(BodyOutline),
            children: [
                { label: '公开', key: 'vpublic', icon: renderIcon(EyeOutline) },
                { label: '私密', key: 'vprivate', icon: renderIcon(EyeOffOutline) }
            ]
        };
    }
    if (useFriendship && post.value.visibility !== VisibilityEnum.FRIEND) {
        visitMenu.children?.push({ label: '好友可见', key: 'vfriend', icon: renderIcon(PersonOutline) })
    }
    options.push(visitMenu);
    return options;
});

const onHandleFollowAction = (post: Item.PostProps) => {
    dialog.success({
        title: '提示',
        content:
            '确定' + (post.user.is_following ? '取消关注 @' : '关注 @') + props.post.user.username + ' 吗？',
        positiveText: '确定',
        negativeText: '取消',
        onPositiveClick: () => {
            if (post.user.is_following) {
                unfollowUser({
                    user_id: post.user.id,
                }).then((_res) => {
                    window.$message.success('操作成功');
                    post.user.is_following = false;
                })
                .catch((_err) => {});
            } else {
                followUser({
                    user_id: post.user.id,
                }).then((_res) => {
                    window.$message.success('操作成功');
                    post.user.is_following = true;
                })
                .catch((_err) => {});
            }
        },
    });
};

const goPostDetail = (id: number) => {
    router.push({
        name: 'post',
        query: {
            id,
        },
    });
};
const doClickText = (e: MouseEvent, id: number) => {
    if ((e.target as any).dataset.detail) {
        const d = (e.target as any).dataset.detail.split(':');
        if (d.length === 2) {
            store.commit('refresh');
            if (d[0] === 'tag') {
                router.push({
                    name: 'home',
                    query: {
                        q: d[1],
                        t: 'tag',
                    },
                });
            } else {
                router.push({
                    name: 'user',
                    query: {
                        s: d[1],
                    },
                });
            }
            return;
        }
    }
    goPostDetail(id);
};
const handlePostAction = (
    item: 'whisper' | 'follow' | 'unfollow' | 'delete' | 'lock' | 'unlock' | 'stick' | 'unstick' | 'highlight' | 'unhighlight' | 'vpublic' | 'vprivate' | 'vfriend' | 'vfollowing' 
) => {
    switch (item) {
        case 'whisper':
            onSendWhisper(props.post.user);
            break;
        case 'follow':
        case 'unfollow':
            onHandleFollowAction(props.post);
            break;
        case 'delete':
            showDelModal.value = true;
            break;
        case 'lock':
        case 'unlock':
            showLockModal.value = true;
            break;
        case 'stick':
        case 'unstick':
            showStickModal.value = true;
            break;
        case 'highlight':
        case 'unhighlight':
            showHighlightModal.value = true;
            break;
        case 'vpublic':
            tempVisibility.value = 0;
            showVisibilityModal.value = true;
            break;
        case 'vprivate':
            tempVisibility.value = 1;
            showVisibilityModal.value = true;
            break;
        case 'vfriend':
            tempVisibility.value = 2;
            showVisibilityModal.value = true;
            break;
        case 'vfollowing':
            tempVisibility.value = 3;
            showVisibilityModal.value = true;
            break;
        default:
            break;
    }
};
const execDelAction = () => {
    deletePost({
        id: post.value.id,
    })
        .then((_res) => {
            window.$message.success('删除成功');
            router.replace('/');

            setTimeout(() => {
                store.commit('refresh');
            }, 50);
        })
        .catch((_err) => {
            loading.value = false;
        });
};
const execLockAction = () => {
    lockPost({
        id: post.value.id,
    })
        .then((res) => {
            emit('reload', post.value.id);
            if (res.lock_status === 1) {
                window.$message.success('锁定成功');
            } else {
                window.$message.success('解锁成功');
            }
        })
        .catch((_err) => {
            loading.value = false;
        });
};
const execStickAction = () => {
    stickPost({
        id: post.value.id,
    })
        .then((res) => {
            emit('reload', post.value.id);
            if (res.top_status === 1) {
                window.$message.success('置顶成功');
            } else {
                window.$message.success('取消置顶成功');
            }
        })
        .catch((_err) => {
            loading.value = false;
        });
};
const execHighlightAction = () => {
    highlightPost({
        id: post.value.id,
    })
        .then((res) => {
            post.value = {
                    ...post.value,
                    is_essence: res.highlight_status,
            };
            if (res.highlight_status === 1) {
                window.$message.success('设为亮点成功');
            } else {
                window.$message.success('取消亮点成功');
            }
        })
        .catch((_err) => {
            loading.value = false;
        });
};
const execVisibilityAction = () => {
    visibilityPost({
        id: post.value.id,
        visibility: tempVisibility.value
    })
        .then((_res) => {
            emit('reload', post.value.id);
            window.$message.success('修改可见性成功');
        })
        .catch((_err) => {
            loading.value = false;
        });
};
const handlePostStar = () => {
    postStar({
        id: post.value.id,
    })
        .then((res) => {
            hasStarred.value = res.status;
            if (res.status) {
                post.value = {
                    ...post.value,
                    upvote_count: post.value.upvote_count + 1,
                };
            } else {
                post.value = {
                    ...post.value,
                    upvote_count: post.value.upvote_count - 1,
                };
            }
        })
        .catch((err) => {
            console.log(err);
        });
};
const handlePostCollection = () => {
    postCollection({
        id: post.value.id,
    })
        .then((res) => {
            hasCollected.value = res.status;
            if (res.status) {
                post.value = {
                    ...post.value,
                    collection_count: post.value.collection_count + 1,
                };
            } else {
                post.value = {
                    ...post.value,
                    collection_count: post.value.collection_count - 1,
                };
            }
        })
        .catch((err) => {
            console.log(err);
        });
};
const handlePostShare = () => {
   copy(`${window.location.origin}/#/post?id=${post.value.id}&share=copy_link&t=${new Date().getTime()}`);
   window.$message.success('链接已复制到剪贴板');
};

onMounted(() => {
    if (store.state.userInfo.id > 0) {
        getPostStar({
            id: post.value.id,
        })
            .then((res) => {
                hasStarred.value = res.status;
            })
            .catch((err) => {
                console.log(err);
            });

        getPostCollection({
            id: post.value.id,
        })
            .then((res) => {
                hasCollected.value = res.status;
            })
            .catch((err) => {
                console.log(err);
            });
    }
});
</script>

<style lang="less">
.detail-item {
    width: 100%;
    padding: 16px;
    box-sizing: border-box;

    background: #f7f9f9;
    .nickname-wrap {
        font-size: 14px;
    }
    .username-wrap {
        font-size: 14px;
        opacity: 0.75;
    }
    .top-tag {
        transform: scale(0.75);
    }
    .options {
        opacity: 0.75;
    }
    .post-text {
        font-size: 16px;
        text-align: justify;
        overflow: hidden;
        white-space: pre-wrap;
        word-break: break-all;
    }
    .opts-wrap {
        margin-top: 20px;
        .opt-item {
            display: flex;
            align-items: center;
            opacity: 0.7;
            .opt-item-icon {
                margin-right: 10px;
            }
            &.hover {
                cursor: pointer;
            }
        }
    }
    .n-thing {
        .n-thing-avatar-header-wrapper {
            align-items: center;
        }
    }
    .timestamp {
        opacity: 0.75;
        font-size: 12px;
        margin-top: 10px;
    }
}
.dark {
    .detail-item {
        background: #18181c;
    }
}
</style>